version: 2
jobs:
  build:
    docker:
      # Ensure .tool-versions matches
      - image: circleci/elixir:1.10.3-node-browsers
        environment:
          MIX_ENV: test
          # match POSTGRES_PASSWORD for postgres image below
          PGPASSWORD: postgres
          # match POSTGRES_USER for postgres image below
          PGUSER: postgres

    working_directory: ~/app

    steps:
      - run: sudo apt-get update; sudo apt-get -y install autoconf build-essential libgmp3-dev libtool

      - checkout
      - run:
          command: ./bin/install_chrome_headless.sh
          no_output_timeout: 2400

      - run: mix local.hex --force
      - run: mix local.rebar --force

      - run:
          name: "ELIXIR_VERSION.lock"
          command: echo "${ELIXIR_VERSION}" > ELIXIR_VERSION.lock
      - run:
          name: "OTP_VERSION.lock"
          command: echo "${OTP_VERSION}" > OTP_VERSION.lock

      - restore_cache:
          keys:
             - v8-mix-compile-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }}-{{ checksum "mix.lock" }}
             - v8-mix-compile-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }}-{{ checksum "mix.exs" }}
             - v8-mix-compile-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }}

      - run: mix deps.get

      - restore_cache:
          keys:
            - v8-npm-install-{{ .Branch }}-{{ checksum "apps/block_scout_web/assets/package-lock.json" }}
            - v8-npm-install-{{ .Branch }}
            - v8-npm-install

      - run:
          command: npm install
          working_directory: "apps/explorer"

      - save_cache:
          key: v3-npm-install-{{ .Branch }}-{{ checksum "apps/explorer/package-lock.json" }}
          paths: "apps/explorer/node_modules"
      - save_cache:
          key: v3-npm-install-{{ .Branch }}
          paths: "apps/explorer/node_modules"
      - save_cache:
          key: v3-npm-install
          paths: "apps/explorer/node_modules"

      - run:
          command: npm install
          working_directory: "apps/block_scout_web/assets"

      - save_cache:
          key: v8-npm-install-{{ .Branch }}-{{ checksum "apps/block_scout_web/assets/package-lock.json" }}
          paths: "apps/block_scout_web/assets/node_modules"
      - save_cache:
          key: v8-npm-install-{{ .Branch }}
          paths: "apps/block_scout_web/assets/node_modules"
      - save_cache:
          key: v8-npm-install
          paths: "apps/block_scout_web/assets/node_modules"

      - run: mix compile

      - run:
          command: make
          working_directory: "deps/ex_secp256k1"

      # `deps` needs to be cached with `_build` because `_build` will symlink into `deps`

      - save_cache:
          key: v8-mix-compile-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }}-{{ checksum "mix.lock" }}
          paths:
            - deps
            - _build
      - save_cache:
          key: v8-mix-compile-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }}-{{ checksum "mix.exs" }}
          paths:
            - deps
            - _build
      - save_cache:
          key: v8-mix-compile-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }}
          paths:
            - deps
            - _build

      - run:
          name: Build assets
          command: node node_modules/webpack/bin/webpack.js --mode development
          working_directory: "apps/block_scout_web/assets"

      - persist_to_workspace:
          root: .
          paths:
            - .circleci
            - .credo.exs
            - .dialyzer-ignore
            - .formatter.exs
            - .git
            - .gitignore
            - ELIXIR_VERSION.lock
            - Gemfile
            - Gemfile.lock
            - OTP_VERSION.lock
            - _build
            - apps
            - bin
            - config
            - deps
            - doc
            - mix.exs
            - mix.lock
            - appspec.yml
            - rel
  check_formatted:
    docker:
      # Ensure .tool-versions matches
      - image: circleci/elixir:1.10.3
        environment:
          MIX_ENV: test

    working_directory: ~/app

    steps:
      - attach_workspace:
          at: .

      - run: mix format --check-formatted
  credo:
    docker:
      # Ensure .tool-versions matches
      - image: circleci/elixir:1.10.3
        environment:
          MIX_ENV: test

    working_directory: ~/app

    steps:
      - attach_workspace:
          at: .

      - run: mix local.hex --force

      - run: mix credo
  deploy_aws:
    docker:
      # Ensure .tool-versions matches
      - image: circleci/python:2.7-stretch

    working_directory: ~/app

    steps:
      - attach_workspace:
          at: .

      - add_ssh_keys:
          fingerprints:
            - "c4:fd:a8:f8:48:a8:09:e5:3e:be:30:62:4d:6f:6f:36"

      - run:
          name: Deploy to AWS
          command: bin/deploy
  dialyzer:
    docker:
      # Ensure .tool-versions matches
      - image: circleci/elixir:1.10.3
        environment:
          MIX_ENV: test

    working_directory: ~/app

    steps:
      - attach_workspace:
          at: .

      - run: mix local.hex --force

      - restore_cache:
          keys:
            - v8-mix-dialyzer-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }}-{{ checksum "mix.lock" }}
            - v8-mix-dialyzer-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }}-{{ checksum "mix.exs" }}
            - v8-mix-dialyzer-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }}

      - run:
          name: Unpack PLT cache
          command: |
            mkdir -p _build/test
            cp plts/dialyxir*.plt _build/test/ || true
            mkdir -p ~/.mix
            cp plts/dialyxir*.plt ~/.mix/ || true

      - run: mix dialyzer --plt

      - run:
          name: Pack PLT cache
          command: |
            mkdir -p plts
            cp _build/test/dialyxir*.plt plts/
            cp ~/.mix/dialyxir*.plt plts/

      - save_cache:
          key: v8-mix-dialyzer-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }}-{{ checksum "mix.lock" }}
          paths:
            - plts
      - save_cache:
          key: v8-mix-dialyzer-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }}-{{ checksum "mix.exs" }}
          paths:
            - plts
      - save_cache:
          key: v8-mix-dialyzer-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }}
          paths:
            - plts

      - run: mix dialyzer --halt-exit-status
  eslint:
    docker:
      # Ensure .tool-versions matches
      - image: circleci/node:12.18.2-browsers-legacy

    working_directory: ~/app

    steps:
      - attach_workspace:
          at: .

      - run:
          name: ESLint
          command: ./node_modules/.bin/eslint --format=junit --output-file="test/eslint/junit.xml" js/**
          working_directory: apps/block_scout_web/assets

      - store_test_results:
          path: apps/block_scout_web/assets/test
  gettext:
    docker:
      # Ensure .tool-versions matches
      - image: circleci/elixir:1.10.3
        environment:
          MIX_ENV: test

    working_directory: ~/app

    steps:
      - attach_workspace:
          at: .

      - run: mix local.hex --force

      - run:
          name: Check for missed translations
          command: |
            mix gettext.extract --merge | tee stdout.txt
            ! grep "Wrote " stdout.txt
          working_directory: "apps/block_scout_web"

      - store_artifacts:
          path: apps/block_scout_web/priv/gettext
  jest:
    docker:
      # Ensure .tool-versions matches
      - image: circleci/node:12.18.2-browsers-legacy

    working_directory: ~/app

    steps:
      - attach_workspace:
          at: .

      - run:
          name: Jest
          command: ./node_modules/.bin/jest
          working_directory: apps/block_scout_web/assets
  release:
    docker:
      # Ensure .tool-versions matches
      - image: circleci/elixir:1.10.3
        environment:
          MIX_ENV: prod

    working_directory: ~/app

    steps:
      - attach_workspace:
          at: .

      - run: mix local.hex --force
      - run: mix local.rebar --force
      - run: MIX_ENV=prod mix release
      - run:
          name: Collecting artifacts
          command: |
            find -name 'blockscout.tar.gz' -exec sh -c 'mkdir -p ci_artifact && cp "$@" ci_artifact/ci_artifact_blockscout.tar.gz' _ {} +
          when: always

      - store_artifacts:
          name: Uploading CI artifacts
          path: ci_artifact/ci_artifact_blockscout.tar.gz
          destination: ci_artifact_blockscout.tar.gz
  sobelow:
    docker:
      # Ensure .tool-versions matches
      - image: circleci/elixir:1.10.3
        environment:
          MIX_ENV: test

    working_directory: ~/app

    steps:
      - attach_workspace:
          at: .

      - run: mix local.hex --force

      - run:
          name: Scan explorer for vulnerabilities
          command: mix sobelow --config
          working_directory: "apps/explorer"

      - run:
          name: Scan block_scout_web for vulnerabilities
          command: mix sobelow --config
          working_directory: "apps/block_scout_web"
  # test_geth_http_websocket:
  #   docker:
  #     # Ensure .tool-versions matches
  #     - image: circleci/elixir:1.10.3-node-browsers
  #       environment:
  #         MIX_ENV: test
  #         # match POSTGRES_PASSWORD for postgres image below
  #         PGPASSWORD: postgres
  #         # match POSTGRES_USER for postgres image below
  #         PGUSER: postgres
  #         ETHEREUM_JSONRPC_CASE: "EthereumJSONRPC.Case.Geth.HTTPWebSocket"
  #         ETHEREUM_JSONRPC_WEB_SOCKET_CASE: "EthereumJSONRPC.WebSocket.Case.Geth"
  #     - image: circleci/postgres:10.10-alpine
  #       environment:
  #         # Match apps/explorer/config/test.exs config :explorer, Explorer.Repo, database
  #         POSTGRES_DB: explorer_test
  #         # match PGPASSWORD for elixir image above
  #         POSTGRES_PASSWORD: postgres
  #         # match PGUSER for elixir image above
  #         POSTGRES_USER: postgres

  #   working_directory: ~/app

  #   steps:
  #     - attach_workspace:
  #         at: .

  #     - run:
  #         command: ./bin/install_chrome_headless.sh
  #         no_output_timeout: 2400

  #     - run: mix local.hex --force
  #     - run: mix local.rebar --force

  #     - run:
  #         name: Wait for DB
  #         command: dockerize -wait tcp://localhost:5432 -timeout 1m

  #     - run:
  #         name: mix test --exclude no_geth
  #         command: |
  #           # Don't submit coverage report for forks, but let the build succeed
  #           if [[ -z "$COVERALLS_REPO_TOKEN" ]]; then
  #             mix coveralls.html --exclude no_geth --parallel --umbrella
  #           else
  #             mix coveralls.circle --exclude no_geth --parallel --umbrella ||
  #               # if mix failed, then coveralls_merge won't run, so signal done here and return original exit status
  #               (retval=$? && curl -k https://coveralls.io/webhook?repo_token=$COVERALLS_REPO_TOKEN -d "payload[build_num]=$CIRCLE_WORKFLOW_WORKSPACE_ID&payload[status]=done" && return $retval)
  #           fi

  #     - store_artifacts:
  #         path: cover/excoveralls.html
  #     - store_test_results:
  #         path: _build/test/junit
  # test_geth_mox:
  #   docker:
  #     # Ensure .tool-versions matches
  #     - image: circleci/elixir:1.10.3-node-browsers
  #       environment:
  #         MIX_ENV: test
  #         # match POSTGRES_PASSWORD for postgres image below
  #         PGPASSWORD: postgres
  #         # match POSTGRES_USER for postgres image below
  #         PGUSER: postgres
  #         ETHEREUM_JSONRPC_CASE: "EthereumJSONRPC.Case.Geth.Mox"
  #         ETHEREUM_JSONRPC_WEB_SOCKET_CASE: "EthereumJSONRPC.WebSocket.Case.Mox"
  #     - image: circleci/postgres:10.10-alpine
  #       environment:
  #         # Match apps/explorer/config/test.exs config :explorer, Explorer.Repo, database
  #         POSTGRES_DB: explorer_test
  #         # match PGPASSWORD for elixir image above
  #         POSTGRES_PASSWORD: postgres
  #         # match PGUSER for elixir image above
  #         POSTGRES_USER: postgres

  #   working_directory: ~/app

  #   steps:
  #     - attach_workspace:
  #         at: .

  #     - run:
  #         command: ./bin/install_chrome_headless.sh
  #         no_output_timeout: 2400

  #     - run: mix local.hex --force
  #     - run: mix local.rebar --force

  #     - run:
  #         name: Wait for DB
  #         command: dockerize -wait tcp://localhost:5432 -timeout 1m

  #     - run:
  #         name: mix test --exclude no_geth
  #         command: |
  #           # Don't submit coverage report for forks, but let the build succeed
  #           if [[ -z "$COVERALLS_REPO_TOKEN" ]]; then
  #             mix coveralls.html --exclude no_geth --parallel --umbrella
  #           else
  #             mix coveralls.circle --exclude no_geth --parallel --umbrella ||
  #               # if mix failed, then coveralls_merge won't run, so signal done here and return original exit status
  #               (retval=$? && curl -k https://coveralls.io/webhook?repo_token=$COVERALLS_REPO_TOKEN -d "payload[build_num]=$CIRCLE_WORKFLOW_WORKSPACE_ID&payload[status]=done" && return $retval)
  #           fi

  #     - store_artifacts:
  #         path: cover/excoveralls.html
  #     - store_test_results:
  #         path: _build/test/junit
  # test_nethermind_http_websocket:
  #   docker:
  #     # Ensure .tool-versions matches
  #     - image: circleci/elixir:1.10.3-node-browsers
  #       environment:
  #         MIX_ENV: test
  #         # match POSTGRES_PASSWORD for postgres image below
  #         PGPASSWORD: postgres
  #         # match POSTGRES_USER for postgres image below
  #         PGUSER: postgres
  #         ETHEREUM_JSONRPC_CASE: "EthereumJSONRPC.Case.Nethermind.HTTPWebSocket"
  #         ETHEREUM_JSONRPC_WEB_SOCKET_CASE: "EthereumJSONRPC.WebSocket.Case.Nethermind"
  #     - image: circleci/postgres:10.10-alpine
  #       environment:
  #         # Match apps/explorer/config/test.exs config :explorer, Explorer.Repo, database
  #         POSTGRES_DB: explorer_test
  #         # match PGPASSWORD for elixir image above
  #         POSTGRES_PASSWORD: postgres
  #         # match PGUSER for elixir image above
  #         POSTGRES_USER: postgres

  #   working_directory: ~/app

  #   steps:
  #     - attach_workspace:
  #         at: .

  #     - run:
  #         command: ./bin/install_chrome_headless.sh
  #         no_output_timeout: 2400

  #     - run: mix local.hex --force
  #     - run: mix local.rebar --force

  #     - run:
  #         name: Wait for DB
  #         command: dockerize -wait tcp://localhost:5432 -timeout 1m

  #     - run:
  #         name: mix test --exclude no_nethermind
  #         command: |
  #           # Don't submit coverage report for forks, but let the build succeed
  #           if [[ -z "$COVERALLS_REPO_TOKEN" ]]; then
  #             mix coveralls.html --exclude no_nethermind --parallel --umbrella
  #           else
  #             mix coveralls.circle --exclude no_nethermind --parallel --umbrella ||
  #               # if mix failed, then coveralls_merge won't run, so signal done here and return original exit status
  #               (retval=$? && curl -k https://coveralls.io/webhook?repo_token=$COVERALLS_REPO_TOKEN -d "payload[build_num]=$CIRCLE_WORKFLOW_WORKSPACE_ID&payload[status]=done" && return $retval)
  #           fi

  #     - store_artifacts:
  #         path: cover/excoveralls.html
  #     - store_test_results:
  #         path: _build/test/junit
  test_nethermind_mox:
    docker:
      # Ensure .tool-versions matches
      - image: circleci/elixir:1.10.3-node-browsers
        environment:
          MIX_ENV: test
          # match POSTGRES_PASSWORD for postgres image below
          PGPASSWORD: postgres
          # match POSTGRES_USER for postgres image below
          PGUSER: postgres
          ETHEREUM_JSONRPC_CASE: "EthereumJSONRPC.Case.Nethermind.Mox"
          ETHEREUM_JSONRPC_WEB_SOCKET_CASE: "EthereumJSONRPC.WebSocket.Case.Mox"
      - image: circleci/postgres:10.10-alpine
        environment:
          # Match apps/explorer/config/test.exs config :explorer, Explorer.Repo, database
          POSTGRES_DB: explorer_test
          # match PGPASSWORD for elixir image above
          POSTGRES_PASSWORD: postgres
          # match PGUSER for elixir image above
          POSTGRES_USER: postgres

    working_directory: ~/app

    steps:
      - attach_workspace:
          at: .

      - run:
          command: ./bin/install_chrome_headless.sh
          no_output_timeout: 2400

      - run: mix local.hex --force
      - run: mix local.rebar --force

      - run:
          name: Wait for DB
          command: dockerize -wait tcp://localhost:5432 -timeout 1m

      - run:
          name: mix test --exclude no_nethermind
          command: |
            # Don't submit coverage report for forks, but let the build succeed
            if [[ -z "$COVERALLS_REPO_TOKEN" ]]; then
              mix coveralls.html --exclude no_nethermind --parallel --umbrella
            else
              mix coveralls.circle --exclude no_nethermind --parallel --umbrella ||
                # if mix failed, then coveralls_merge won't run, so signal done here and return original exit status
                (retval=$? && curl -k https://coveralls.io/webhook?repo_token=$COVERALLS_REPO_TOKEN -d "payload[build_num]=$CIRCLE_WORKFLOW_WORKSPACE_ID&payload[status]=done" && return $retval)
            fi

      - store_artifacts:
          path: cover/excoveralls.html
      - store_test_results:
          path: _build/test/junit
  coveralls_merge:
    docker:
      # Ensure .tool-versions matches
      - image: circleci/elixir:1.10.3
        environment:
          MIX_ENV: test

    steps:
      - run:
          name: Tell coveralls.io build is done
          command: curl -k https://coveralls.io/webhook?repo_token=$COVERALLS_REPO_TOKEN -d "payload[build_num]=$CIRCLE_WORKFLOW_WORKSPACE_ID&payload[status]=done"
workflows:
  version: 2
  primary:
    jobs:
      - build
      - check_formatted:
          requires:
            - build
      # This unfortunately will only fire if all the tests pass because of how `requires` works
      - coveralls_merge:
          requires:
            # - test_nethermind_http_websocket
            - test_nethermind_mox
            # - test_geth_http_websocket
            # - test_geth_mox
      - credo:
          requires:
            - build
      - deploy_aws:
          filters:
            branches:
              only:
                - production
                - staging
                - /deploy-[A-Za-z0-9]+$/
          requires:
            - check_formatted
            - credo
            - eslint
            - jest
            - sobelow
            # - test_nethermind_http_websocket
            - test_nethermind_mox
            # - test_geth_http_websocket
            # - test_geth_mox
      - dialyzer:
          requires:
            - build
      - eslint:
          requires:
            - build
      - gettext:
          requires:
            - build
      - jest:
          requires:
            - build
      - release:
          requires:
            - build
      - sobelow:
          requires:
            - build
      # - test_nethermind_http_websocket:
      #     requires:
      #       - build
      - test_nethermind_mox:
          requires:
            - build
      # - test_geth_http_websocket:
      #     requires:
      #       - build
      # - test_geth_mox:
      #     requires:
      #       - build
